;; Connect to the Pleroma instance and dump the home timeline onto
;; your screen. This example demonstrates how to authenticate with the
;; server, get the necessary tokens and serialize them to a file. The
;; client is serialized to the local file "_client". If there is an
;; error you can regenerate the authorization data by removing the
;; "_client" file.

;; run as `guile -s example.scm`
;; geiser: C-c C-e C-l to add "." to the load path
(use-modules
 (ice-9 rdelim)
 (ice-9 format)
 (ice-9 match)
 (srfi srfi-1)
 (web uri)
 ;; local
 (tapris client))


(define instance (string->uri "https://satania.space"))

(define (ask-for-code client)
  (let ((u (build-authorize-url client)))
    (format #t "Please visit the following URL to obtain the \
authorization code: ~a\nPlease input the code: " (uri->string u))))

(define (client->list client)
  (match client
    (($ <client> instance id secret token)
     (list (uri->string instance) id secret token))))

(define (list->client ls)
  (match ls
    ((instance id secret token)
     (make-client (string->uri instance) id secret token))))

(define (new-client instance)
  (let ((client (register-app instance)))
    (ask-for-code client)
    (let* ((auth-code (read-line))
           (token (get-token client auth-code)))
      (set-client-token! client token)
      (format #t "Trying to verify the token ~a.\n" auth-code)
      (catch 'pleroma (lambda () (verify-credentials client))
        (lambda (keys . args)
          (format #t "Error!\n")
          (for-each (lambda (a) (format #t "-- ~a\n" a)) args)
          (exit 1)))
      (format #t "Verifcation succeeded! Saving the client data locally.\n")
      (let ((port (open-output-file "_client")))
        (write (client->list client) port)
        (close-port port)
        client))))

(define (obtain-client)
  (define (try-read)
    (let* ((port (open-input-file "_client"))
           (client (list->client (read port))))
      (close-port port)
      client))
  (catch 'system-error try-read
    (lambda (key . args)
      (match args
        (("open-file" fmt . rest)
         ;; Need to get a new token.
         (new-client instance))
        (_ (apply throw (cons 'system-error args)))))))


(define client (obtain-client))

(define sts (get-home-timeline client))

(define (format-status st)
  (let ((content (status-content st))
        (from (assoc-ref (status-account st) "username"))
        (medias (map (lambda (m)
                       (assoc-ref m "url"))
                     (vector->list (status-media-attachments st)))))
    (format #t "~a: ~a\n\n" from content)))

(for-each format-status sts)
